package com.eurasia.assignment.service;

import java.io.IOException;
import java.util.List;
import java.util.stream.Collectors;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import com.eurasia.assignment.controller.dto.CreateProjectRequest;
import com.eurasia.assignment.controller.dto.ProjectSearchRequest;
import com.eurasia.assignment.domain.Project;
import com.eurasia.assignment.infrastructure.entity.FileEntity;
import com.eurasia.assignment.infrastructure.entity.ProjectEntity;
import com.eurasia.assignment.infrastructure.repository.ProjectRepository;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * 项目服务类
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class ProjectService {

    private final ProjectRepository projectRepository;
    private final FileService fileService;

    /**
     * 创建新项目
     * @param request 项目创建请求
     * @return 创建的项目
     */
    @Transactional
    public Project createProject(CreateProjectRequest request) {
        // 创建项目对象
        Project project = Project.create(
            request.getName(),
            request.getType(),
            request.getCourse(),
            request.getPoints(),
            request.getCreator()
        );
        
        // 设置附加字段
        if (request.getStartTime() != null && !request.getStartTime().isEmpty()) {
            try {
                project.setStartTime(java.time.LocalDateTime.parse(request.getStartTime()));
            } catch (Exception e) {
                log.warn("无法解析开始时间: {}", request.getStartTime());
            }
        }
        
        if (request.getFinishTime() != null && !request.getFinishTime().isEmpty()) {
            try {
                project.setFinishTime(java.time.LocalDateTime.parse(request.getFinishTime()));
            } catch (Exception e) {
                log.warn("无法解析结束时间: {}", request.getFinishTime());
            }
        }
        
        project.setComment(request.getComment());
        
        // 保存到数据库
        var savedProject = projectRepository.save(ProjectEntity.fromDomain(project));

        return savedProject.toDomain();
    }
    
    /**
     * 创建带有文件的新项目
     * @param request 项目创建请求
     * @param file 上传的文件
     * @return 创建的项目
     */
    @Transactional
    public Project createProjectWithFile(CreateProjectRequest request, MultipartFile file) {
        Long fileId = null;
        
        // 处理文件上传
        if (file != null && !file.isEmpty()) {
            try {
                FileEntity fileEntity = fileService.saveFile(file);
                fileId = fileEntity.getId();
                log.info("文件上传成功并关联到项目: {}", fileEntity.getOriginalFileName());
            } catch (IOException e) {
                log.error("文件上传失败", e);
            }
        }
        
        // 创建项目对象
        Project project = Project.createFullProject(
            request.getName(),
            request.getType(),
            request.getCourse(),
            request.getPoints(),
            request.getCreator(),
            request.getStartTime(),
            request.getFinishTime(),
            request.getComment(),
            fileId
        );
        
        // 保存到数据库
        var savedProject = projectRepository.save(ProjectEntity.fromDomain(project));

        return savedProject.toDomain();
    }
    
    /**
     * 获取所有项目
     * @return 项目列表
     */
    public List<Project> getAllProjects() {
        return projectRepository.findAll().stream()
                .map(ProjectEntity::toDomain)
                .collect(Collectors.toList());
    }
    
    /**
     * 根据ID获取项目
     * @param id 项目ID
     * @return 项目对象
     */
    public Project getProjectById(Long id) {
        return projectRepository.findById(id)
                .map(ProjectEntity::toDomain)
                .orElseThrow(() -> new IllegalArgumentException("项目不存在：" + id));
    }
    
    /**
     * 分页搜索项目
     * @param searchRequest 搜索条件
     * @return 分页结果
     */
    public Page<Project> searchProjectsWithPagination(ProjectSearchRequest searchRequest) {
        // 获取分页和排序参数
        int page = searchRequest.getPage() != null ? searchRequest.getPage() : 0;
        int size = searchRequest.getSize() != null ? searchRequest.getSize() : 10;
        
        // 处理排序
        org.springframework.data.domain.Sort sort = null;
        
        if (StringUtils.hasText(searchRequest.getSortBy())) {
            sort = "desc".equalsIgnoreCase(searchRequest.getSortDirection()) 
                ? org.springframework.data.domain.Sort.by(searchRequest.getSortBy()).descending()
                : org.springframework.data.domain.Sort.by(searchRequest.getSortBy()).ascending();
        }
        
        // 创建分页对象
        Pageable pageable = sort != null 
            ? PageRequest.of(page, size, sort) 
            : PageRequest.of(page, size);
        
        Page<ProjectEntity> projectPage;
        
        // 根据不同条件组合进行查询
        boolean hasName = StringUtils.hasText(searchRequest.getName());
        boolean hasType = StringUtils.hasText(searchRequest.getType());
        boolean hasStatus = StringUtils.hasText(searchRequest.getStatus());
        
        if (hasName && hasType && hasStatus) {
            projectPage = projectRepository.findByNameContainingAndTypeAndStatus(
                searchRequest.getName(),
                searchRequest.getType(),
                searchRequest.getStatus(),
                pageable
            );
        } else if (hasName && hasType) {
            projectPage = projectRepository.findByNameContainingAndType(
                searchRequest.getName(),
                searchRequest.getType(),
                pageable
            );
        } else if (hasName && hasStatus) {
            projectPage = projectRepository.findByNameContainingAndStatus(
                searchRequest.getName(),
                searchRequest.getStatus(),
                pageable
            );
        } else if (hasType && hasStatus) {
            projectPage = projectRepository.findByTypeAndStatus(
                searchRequest.getType(),
                searchRequest.getStatus(),
                pageable
            );
        } else if (hasName) {
            projectPage = projectRepository.findByNameContaining(
                searchRequest.getName(),
                pageable
            );
        } else if (hasType) {
            projectPage = projectRepository.findByType(
                searchRequest.getType(),
                pageable
            );
        } else if (hasStatus) {
            projectPage = projectRepository.findByStatus(
                searchRequest.getStatus(),
                pageable
            );
        } else {
            projectPage = projectRepository.findAll(pageable);
        }
        
        log.debug("查询结果: 总条数={}, 总页数={}, 当前页记录数={}",
            projectPage.getTotalElements(),
            projectPage.getTotalPages(),
            projectPage.getNumberOfElements());
        
        return projectPage.map(ProjectEntity::toDomain);
    }
    
    /**
     * 删除项目
     * @param id 项目ID
     */
    @Transactional
    public void deleteProject(Long id) {
        if (!projectRepository.existsById(id)) {
            throw new IllegalArgumentException("项目不存在：" + id);
        }
        projectRepository.deleteById(id);
    }
    
    /**
     * 更新项目
     * @param id 项目ID
     * @param projectDetails 项目详情
     * @return 更新后的项目
     */
    @Transactional
    public Project updateProject(Long id, Project projectDetails) {
        ProjectEntity projectEntity = projectRepository.findById(id)
                .orElseThrow(() -> new IllegalArgumentException("项目不存在：" + id));
                
        projectEntity.setName(projectDetails.getName());
        projectEntity.setType(projectDetails.getType());
        projectEntity.setCourseId(projectDetails.getCourse());
        projectEntity.setStatus(projectDetails.getStatus());
        projectEntity.setPoints(projectDetails.getPoints());
        projectEntity.setCreator(projectDetails.getCreator());
        
        return projectRepository.save(projectEntity).toDomain();
    }
}